package com.flyqiu.common.property;

import com.flyqiu.common.std.FlyQiuBooleanFun;

import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;

/**
 * 使用 JavaBeans 的 PropertyDescriptor 来实现属性访问。
 * <p>
 * 此类提供了对 JavaBeans 属性的读取和写入操作。
 */
public class FlyQiuPropertyDesc implements FlyQiuBaseProperty {

    private final PropertyDescriptor propertyDescriptor;
    private final Method readMethod;
    private final Method writeMethod;
    private final List<Annotation> propertyAnnotations;

    /**
     * 构造一个新的 FlyQiuPropertyDes 对象。
     *
     * @param propertyDescriptor 属性描述符
     */
    public FlyQiuPropertyDesc(PropertyDescriptor propertyDescriptor) {
        this.propertyDescriptor = propertyDescriptor;
        this.readMethod = propertyDescriptor.getReadMethod();
        this.writeMethod = propertyDescriptor.getWriteMethod();
        propertyAnnotations = new ArrayList<>();

        propertyAnnotations.addAll(Arrays.asList(readMethod.getAnnotations()));
        propertyAnnotations.addAll(Arrays.asList(writeMethod.getAnnotations()));


    }

    /**
     * 判断属性是否可读。
     *
     * @return 如果属性可读，则返回 true；否则返回 false
     */
    @Override
    public boolean isRead() {
        return readMethod != null;
    }

    /**
     * 判断属性是否可写。
     *
     * @return 如果属性可写，则返回 true；否则返回 false
     */
    @Override
    public boolean isWrite() {
        return writeMethod != null;
    }

    /**
     * 判断属性是否为静态属性。
     *
     * @return 如果属性为静态属性，则返回 true；否则返回 false
     */
    @Override
    public boolean isStatic() {
        return Modifier.isStatic(readMethod.getModifiers()) || Modifier.isStatic(writeMethod.getModifiers());
    }

    /**
     * 获取属性的名称。
     *
     * @return 属性名称
     */
    @Override
    public String getName() {
        return propertyDescriptor.getName();
    }

    /**
     * 获取属性的数据类型。
     *
     * @return 属性的数据类型
     */
    @Override
    public Class<?> getType() {
        return propertyDescriptor.getPropertyType();
    }

    @Override
    public <T extends Annotation> List<T> getAnnotations(FlyQiuBooleanFun<Annotation> filter, Function<Annotation, T> valueMapper) {
        if (filter == null) {
            throw new NullPointerException("filter cannot be null");
        }
        if (valueMapper == null) {
            throw new NullPointerException("filter cannot be null");
        }

        List<T> result = new ArrayList<>();
        for (Annotation annotation : propertyAnnotations) {
            if (!filter.apply(annotation)) {
                continue;
            }
            result.add(valueMapper.apply(annotation));
        }
        return result;
    }

    /**
     * 获取属性的值。
     *
     * @param obj 对象实例
     * @return 属性的值
     * @throws IllegalStateException 如果属性不可读
     */
    @Override
    public Object getValue(Object obj) {
        if (!isRead()) {
            throw new IllegalStateException("Property '" + getName() + "' in class " + obj.getClass().getName() + " is not readable");
        }
        try {
            return readMethod.invoke(obj);
        } catch (IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException("Error invoking getter method for property '" + getName() + "'", e);
        }
    }

    /**
     * 设置属性的值。
     *
     * @param obj 对象实例
     * @param val 属性的新值
     * @throws IllegalStateException 如果属性不可写
     */
    @Override
    public void setValue(Object obj, Object val) {
        if (!isWrite()) {
            throw new IllegalStateException("Property '" + getName() + "' in class " + obj.getClass().getName() + " is not writable");
        }
        try {
            writeMethod.invoke(obj, val);
        } catch (IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException("Error invoking setter method for property '" + getName() + "'", e);
        }
    }
}
